package com.feishi.core.media.javacv.util;

import com.feishi.core.util.common.bean.WaveData;
import com.feishi.core.util.compress.CompressUtil;
import org.bytedeco.javacpp.opencv_core.IplImage;
import org.bytedeco.javacpp.opencv_core.Mat;
import org.bytedeco.javacpp.opencv_core.Size;

import java.nio.ByteBuffer;

import static org.bytedeco.javacpp.opencv_core.absdiff;
import static org.bytedeco.javacpp.opencv_imgcodecs.imwrite;
import static org.bytedeco.javacpp.opencv_imgproc.*;


/**
 * @version 1.0
 * @auth caixq
 * @time 18-4-24 13:17
 **/
public class FindMove {
    Mat preMat;
    //    Mat currentGrayMat=new Mat();
    Mat diff = new Mat();

    private WaveData waveData = new WaveData(100);
    private WaveData waveData2 = new WaveData(200);
    private Mat diff_thresh = new Mat();
    private Mat gray = new Mat();

    private Mat kernel_erode = getStructuringElement(MORPH_RECT, new Size(3, 3));


    public Mat onMatReceive(Mat currentMat) {

        //1.将currentMat转为灰度图
        cvtColor(currentMat, this.gray, COLOR_BGR2GRAY);
//        currentMat=this.gray;
        preMat = preMat == null ? currentMat.clone() : preMat;

        boolean b = moveDetect(preMat, currentMat);


//        cvtColor(currentMat, this.preMat, COLOR_BGR2BGRA);
        preMat.release();

        preMat = currentMat.clone();

        return b ? currentMat : null;
    }
    int i=0;
    private boolean moveDetect(Mat preMat, Mat currentMat) {

        //2.将background和frame做差

        absdiff(currentMat, preMat, diff);
        //3.对差值图diff_thresh进行阈值化处理
        threshold(diff, diff_thresh, 50, 255, THRESH_BINARY);
        //4.腐蚀
        erode(diff_thresh, diff_thresh, kernel_erode);
        ByteBuffer bs = diff_thresh.createBuffer();
        int size = CompressUtil.gZip(OpenCvUtil.MatToBytes(diff_thresh, ".png")).length;
//        System.out.println(size);
        boolean result = waveData.isWaveData((double) size);
        waveData.addData((double) size);
        System.out.println(size);

        return result;//返回result
    }
    byte[] pre;
    byte[] current;
    byte[] df;
    private int width;
    private int height;
    private int widthStep;
    private int nchannal;
    public IplImage onMatReceive(IplImage mat){
        ByteBuffer buffer=mat.createBuffer();
        if(pre==null){
            pre=new byte[buffer.remaining()];
            current=new byte[buffer.remaining()];
            df=new byte[buffer.remaining()];
            buffer.get(pre);
            this.width=mat.width();
            this.height=mat.height();
            this.widthStep=mat.widthStep();
            this.nchannal=mat.nChannels();
            return mat;
        }
        buffer.get(current);
        ((ByteBuffer)mat.createBuffer()).put(current);
//        buffer.reset();
        int count=0;
        for(int y=0;y<height;y++){
            for(int x=0;x<width;x++){
                int index=widthStep*y+nchannal*x;
                count+=move(index,nchannal);
                diff(index,nchannal);
                copy(index,nchannal);
            }
        }

//        int size = CompressUtil.gZip(df).length;
//        boolean result2 = waveData2.isWaveData((double) size);

        boolean result= waveData.addCommonData((double) count);
//        waveData2.addData((double) size);

        if(result){
            return mat;
        }else {
            return null;
        }
    }

    private void diff(int index, int width) {
        for (int j = 0; j < width; j++) {
            df[index+j]= (byte) (pre[index+j]-current[index+j]);
        }
    }

    private int move(int index, int width) {
        int sum=0;
        for (int j = 0; j < width; j++) {
            sum+=Math.abs(pre[index+j]-current[index+j]);
        }
        return sum;
    }

    private void copy(int index, int width) {
        for (int j = 0; j < width; j++) {
            pre[index+j]=current[index+j];
        }
    }

}
